﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine.Dtd.Schema;
using System.Xml;
using System.Diagnostics;

namespace Engine.Sgml.Parser {
    internal sealed class ElementReader : IElementReader {
        private AttributeReader attributeReader;

        public ElementReader(AttributeReader attributeReader) {
            Guard.ArgumentNotNull(attributeReader, "attributeReader");
            this.attributeReader = attributeReader;
            }

        public SElement Read(SgmlStreamReader reader, SElement parent, Context context) {
            SElement element = parent.Nodes.Push();
            element.Clear();
            element.Parent = parent;
            element.LineNumber = context.LineNumber;
            element.LinePosition = context.LinePosition;

            if (reader.CurrentChar == Characters.ClosingTagMarkup) {
                // Consume '/' symbol.
                reader.ReadChar();
                element.NodeType = SgmlNodeType.EndElement;
                string name = context.NameReader.ScanPrefixNameToken(reader);
                if (name == null)
                    name = parent.Name;
                element.Name = name;
                element.InitializeDeclaration(context.Schema, context.Behavior.CaseSensitiveTags);
                if (reader.SkipWhitespace() == Characters.EndTagMarkup)
                    reader.ReadChar();
                else
                    context.TraceSource.TraceEvent(TraceEventType.Error, 0, "Expected end tag '>' sequence instead of '{0}'. {1}", reader.CurrentChar, reader.Context());
                }
            else {
                element.NodeType = SgmlNodeType.Element;
                string name = context.NameReader.ScanPrefixNameToken(reader);
                if (name == null)
                    name = parent.Name;
                element.Name = name;
                element.InitializeDeclaration(context.Schema, context.Behavior.CaseSensitiveTags);
                attributeReader.Read(reader, element, context);
                if (reader.CurrentChar == Characters.ClosingTagMarkup) {
                    element.IsEmpty = true;
                    reader.ReadChar();
                    }
                if (reader.CurrentChar == Characters.EndTagMarkup)
                    reader.ReadChar();
                else
                    context.TraceSource.TraceEvent(TraceEventType.Error, 0, "Start element '{0}' is missing '>'. {1}", element.LocalName, reader.Context());
                }
            return element;
            }
        }
    }
